﻿using System;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using YmtAuth.Common.Utility;
using YmtAuth.Domain.Model.Safe;

namespace YmtAuth.Domain.EventHistory
{
    /// <summary>
    /// 用户登录事件领域规则
    /// </summary>
    public class LoginEventSpecifications
    {
        /// <summary>
        /// 匹配登录密码错误超限。默认5分钟内
        /// </summary>
        /// <param name="loginId"></param>
        /// <returns></returns>
        public static IMongoQuery MatchLoginPasswordErrorLimit(string loginId, TimeSpan time = default(TimeSpan))
        {
            var _time = DateTime.Now.AddMinutes(-5);
            if (time != default(TimeSpan))
                _time = DateTime.Now.Add(time);
            var _loginId = loginId.ToLower();
            //return e => e.sLoginId == _loginId && e.iAction == 0 && e.dAddTime > _time;
            return Query.And(Query.EQ("sLoginId", _loginId)
                , Query.GT("dAddTime", _time)
                //, Query.Or(Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess), Query.EQ("iAction", 0))
                , Query.EQ("ResponseCode", AuthSafeHandleCode.LoginPasswordError)
                );
        }

        public static IMongoQuery MatchLoginFailLimitMongoQuery(string loginId, TimeSpan time = default(TimeSpan))
        {
            var _time = DateTime.Now.AddMinutes(-5);
            if (time != default(TimeSpan))
                _time = DateTime.Now.Add(time);
            var _loginId = loginId.ToLower();
            //return Query.And(Query<YmtUserLoginEvent>.EQ(e => e.sLoginId, _loginId),
            //     Query<YmtUserLoginEvent>.EQ(e => e.iAction, 0), Query<YmtUserLoginEvent>.GTE(e => e.dAddTime, _time));           
            return Query.And(Query.EQ("sLoginId", _loginId)
                , Query.GT("dAddTime", _time)
                //, Query.Or(Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess), Query.EQ("iAction", 0))
                , Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                );
        }

        /// <summary>
        /// 生成登录指定格式KEY
        /// </summary>
        /// <param name="loginId"></param>
        /// <returns></returns>
        public static string GenerateLoginSpecKey(string loginId,int code)
        {
            return string.Format("{0}_{1}", new Encrypt().Md5Encrypt(loginId),code);
        }

        /// <summary>
        /// 生成设备登录指定格式KEY
        /// </summary>
        /// <param name="DeviceType"></param>
        /// <param name="deviceId"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static string GenerateLoginDeviceSpecKey(byte DeviceType, string deviceId, bool success)
        {
            return string.Format("{0}_{1}_{2}", DeviceType, success, deviceId);
        }

        /// <summary>
        /// 生成登录KEY
        /// </summary>
        /// <param name="loginId"></param>
        /// <returns></returns>
        public static string GenerateLoginKey(string loginId)
        {
            return new Encrypt().Md5Encrypt(loginId);
        }

        public static IMongoQuery MatchLoginPasswordFail(string loginId, int loginFailTimeMinutes)
        {
            var _loginId = loginId.ToLower();
            var _time = loginFailTimeMinutes > 0 ? -loginFailTimeMinutes : loginFailTimeMinutes;
            var subTime = DateTime.Now.AddMinutes(_time);
            return Query.And(Query.EQ("sLoginId", _loginId)
                , Query.GT("dAddTime", subTime)
                , Query.EQ("ResponseCode", AuthSafeHandleCode.LoginPasswordError)
                );
        }
        /// <summary>
        /// 匹配登录密码错误失败时间段
        /// </summary>
        /// <param name="loginFailTimeMinutes"></param>
        /// <returns></returns>
        public static DateTime MatchLoginPasswordFailTime(int loginFailTimeMinutes)
        {
            var _time = loginFailTimeMinutes > 0 ? -loginFailTimeMinutes : loginFailTimeMinutes;
            var subTime = DateTime.Now.AddMinutes(_time);
            return subTime;
        }

        public static IMongoQuery MatchLoginFailLimitByIp(string loginIp, TimeSpan time = default(TimeSpan))
        {
            var _time = DateTime.Now.AddMinutes(-5);
            if (time != default(TimeSpan))
                _time = DateTime.Now.Add(time);
            var _ip = loginIp.ToLower();
            //return e => e.sLoginIp == _ip
            //    && e.iAction == 0
            //    && e.dAddTime > _time;
            return Query.And(Query.EQ("sLoginIp", _ip)
                //, Query.Or(Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess), Query.EQ("iAction", 0))
                , Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                , Query.GT("dAddTime", _time));
        }

        public static IMongoQuery MatchLoginSuccessLimitByIp(string loginIp, TimeSpan time = default(TimeSpan))
        {
            var _time = DateTime.Now.AddMinutes(-5);
            if (time != default(TimeSpan))
                _time = DateTime.Now.Add(time);
            var _ip = loginIp.ToLower();
            //return e => e.sLoginIp == _ip
            //    && e.iAction > 0
            //    && e.dAddTime > _time;
            return Query.And(Query.EQ("sLoginIp", _ip)
                //,Query.Or(Query.EQ("ResponseCode",AuthSafeHandleCode.LoginSuccess),Query.GT("iAction", 0))
                , Query.EQ("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                , Query.GT("dAddTime", _time));
        }

        public static IMongoQuery MatchLoginCount(string loginId, TimeSpan time = default(TimeSpan))
        {
            var _time = DateTime.Now.AddMinutes(-5);
            if (time != default(TimeSpan))
                _time = DateTime.Now.Subtract(time);
            var _loginId = loginId.ToLower();
            //return e => e.sLoginId == _loginId && e.dAddTime > _time;
            return Query.And(Query.EQ("sLoginId", _loginId), Query.GT("dAddTime", _time));
        }

        public static IMongoQuery MatchLoginSuccessDeviceId(string deviceId, string clientId, int time)
        {
            var _time = time > 0 ? DateTime.Now.AddMinutes(-time) : DateTime.Now.AddMinutes(time);
            var query = Query.Null;
            if (!deviceId.IsEmpty())
                query = Query.EQ("DeviceId", deviceId);
            if (deviceId.IsEmpty() && !clientId.IsEmpty())
                query = Query.EQ("ClientId", clientId);
            if (query != Query.Null)
            {
                return Query.And(
                    query
                    , Query.EQ("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                    , Query.GT("dAddTime", _time));
            }

            return Query.And(
                Query.EQ("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                , Query.GT("dAddTime", _time));
        }

        public static IMongoQuery MatchLoginFailDeviceId(string deviceId, string clientId, int time)
        {
            var _time = time > 0 ? DateTime.Now.AddMinutes(-time) : DateTime.Now.AddMinutes(time);
            var query = Query.Null;
            if (!deviceId.IsEmpty())
                query = Query.EQ("DeviceId", deviceId);
            if (deviceId.IsEmpty() && !clientId.IsEmpty())
                query = Query.EQ("ClientId", clientId);
            if (query != Query.Null)
            {
                return Query.And(
                    query
                    , Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                    , Query.GT("dAddTime", _time));
            }
            return Query.And(
                Query.NE("ResponseCode", AuthSafeHandleCode.LoginSuccess)
                , Query.GT("dAddTime", _time));
        }
       
        public static readonly string LoginLogDb = "Ymt_LoginHistory";

        public static string LoginLogTb()
        {            
            return "LoginHistory";
        }

        public static DateTime GenerateLoginIpDateTime(int minutes)
        {
            var _minutes = minutes > 0 ? -minutes : minutes;
            return DateTime.Now.AddMinutes(_minutes);
        }

        /// <summary>
        /// 认证服务登录失败KEY
        /// </summary>
        public static readonly string AUTHSERVICE_LOGIN_FAIL_IP_KEY = "loginipfail";
        /// <summary>
        /// 认证服务登录成功KEY
        /// </summary>
        public static readonly string AUTHSERVICE_LOGIN_FAIL_SUCCESS_KEY = "loginipok";
        /// <summary>
        /// 认证服务登录次数KEY
        /// </summary>
        public static readonly string AUTHSERVICE_LOGIN_COUNT_KEY = "logincount";
        /// <summary>
        /// 认证服务计数器KEY
        /// </summary>
        public static readonly string AUTHSERVICE_KEY = "auth";

        /// <summary>
        /// 登录，设备/ClientId 登录成功计数
        /// </summary>
        public static readonly string AUTHSERVICE_LOGIN_DEVICE_SUCCESS_KEY = "logindevicesuccess";

        /// <summary>
        /// 登录，设备/ClientId 登录失败计数
        /// </summary>
        public static readonly string AUTHSERVICE_LOGIN_DEVICE_FAIL_KEY = "logindevicefail";
    }
}
